复制结构体(创建一份拷贝) 您所在的位置:网站首页 go 值拷贝 复制结构体(创建一份拷贝)

复制结构体(创建一份拷贝)

2024-07-17 17:25| 来源: 网络整理| 查看: 265

复制结构体(创建一份拷贝)

结构体的复制用赋值语句这种简单的形式。

package main import "fmt" type T struct { I int S string } func main() { // initialize a struct t := T{1, "one"} // make struct copy u := t // u has its field values equal to t if u == t { // true fmt.Println("u and t are equal") // Prints: "u and t are equal" fmt.Printf("u address is: %p\nt address is:%p\n", &u, &t) } }u and t are equal u address is: 0xc00000c0c0 t address is:0xc00000c0a0

上例中,t 和 u 就是独立的对象(结构体)了。

因为类型T中不包含任何引用类型(切片slice、映射map、数据通道channel)作为它的字段,因此对t和u的值进行修改并不会彼此影响。

t.I, u.I = 100, 1 fmt.Printf("t.I = %d, u.I = %d\n", t.I, u.I)

然而,假如T中包含的有引用类型,比如:

type T struct { I int S string xs []int // a slice is a reference type }

如果还只是简单地用赋值语句来拷贝对象,其结果是两个不同的对象引用了相同的切片。

// initialize a struct t := T{I: 1, S: "one", xs: []int{1, 2, 3}} // make struct copy u := t // u has its field values equal to t

因为u和t都指向了相同的切片,因此在一个变量中修改了切片,另一个变量也会受影响而改变。

// update a slice field in u u.xs[1] = 500 fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs) // t.xs = [1 500 3], u.xs = [1 500 3]

因此,在复制包含引用类型的结构体时需要十分小心,记住这个特性,否则可能会出现意料不到的错误。

如果要结构体中引用类型字段也真实拷贝独立存在,修改其中一个而不影响另一个,需要像下面这样显式地完成复制:

// explicitly initialize u's slice field u.xs = make([]int, len(t.xs)) // copy the slice values over from t copy(u.xs, t.xs) // updating slice value in u will not affect t u.xs[1] = 500 fmt.Printf("t.xs = %d, u.xs = %d\n", t.xs, u.xs) // t.xs = [1 2 3], u.xs = [1 500 3]译者注

本节谈论的利用赋值语句隐式拷贝和make函数显式拷贝的区别,实际上就是浅拷贝和深拷贝的区别。

在用赋值语句拷贝时,系统虽然为u.xs分配了新内存地址用于存放值,此地址与t.xs不同,但所存放的值并不是具体的切片[1 2 3],而是原切片的指针。在赋值语句发生拷贝的瞬间,复制了指针,而不是复制了值,所以指向了相同的内存空间。

上一页结构体标签下一页空结构体

最后更新于4年前



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有